package abstractGA.result;

import java.util.List;

import abstractGA.GAParameter;

import java.util.ArrayList;

import foundation.fileUtil.DataCell;


public class OutData {

	AbsGADAO dbAccess = new AbsGADAO();
	GAParameter gaPara = null;

	public OutData(GAParameter gaPara) {
		this.gaPara = gaPara;
	}

	public void outDatabase(OneOpt oneOpt) {
		dbAccess.addAlgRun(oneOpt);
	}

	/**
	 * 请晓斌完成
	 * 这个方法相当于“期望的结果输出表.xls”中的名为“2”的表单
	 * @param runID
	 * @return
	 */
	public List<List<DataCell>> getBestChromsOut(String runID){
		List<ChromOut> chromOuts = dbAccess.getBestChroms(runID);
		List<List<DataCell>> rlts = new ArrayList<List<DataCell>>();
		/*
		 * 建标题行
		 */
		List<DataCell> titleRow = new ArrayList<DataCell>();
		// 染色体编码
		DataCell codeTitleCell = new DataCell();
		codeTitleCell.setName("染色体编码");
		titleRow.add(codeTitleCell);
		// 目标值
		DataCell objValsTitleCell = new DataCell();
		objValsTitleCell.setName("目标值(响应时间,可靠性,代价)");
		titleRow.add(objValsTitleCell);
		// 变更元素
		DataCell chgedElems = new DataCell();
		chgedElems.setName("变更元素");
		titleRow.add(chgedElems);
		// 演化代数
		DataCell genID = new DataCell();
		genID.setName("演化代数");
		titleRow.add(genID);
		rlts.add(titleRow);

		
		for (int i=0;i<chromOuts.size();i++){
			List<DataCell> row = new ArrayList<DataCell>();
			DataCell codesDataCell = new DataCell();
			codesDataCell.setName(chromOuts.get(i).getCodes());
			row.add(codesDataCell);
			DataCell objValDataCell = new DataCell();
			objValDataCell.setName("objVal1="+chromOuts.get(i).getObjVal1()+
					",objVal2="+chromOuts.get(i).getObjVal2()+
					",objVal3="+chromOuts.get(i).getObjVal3());
			row.add(objValDataCell);
			DataCell chgedElemsDataCell = new DataCell();
			chgedElemsDataCell.setName(chromOuts.get(i).getChgedElems());
			row.add(chgedElemsDataCell);
			DataCell genIDDataCell = new DataCell();
			genIDDataCell.setName(chromOuts.get(i).getGenID());
			row.add(genIDDataCell);
			
			rlts.add(row);
		}
		
		return rlts;
	}
	/*
	 * 求多次运行中，第i代最优目标值的均值，反映收敛到最优解的速度
	 */
	public List<List<DataCell>> getAveOfObj(ArrayList<String> runIDs,int maxIterNum) {
		List<List<DataCell>> rlts = new ArrayList<List<DataCell>>();
		//第i代最优目标值1和目标值2之和，其中目标值2暂不考虑
		Float[] sumOfObjVal1 = new Float[maxIterNum];
		Float[] sumOfObjVal2 = new Float[maxIterNum];
		Float[] sumOfObjVal3 = new Float[maxIterNum];
		//从1到maxIterNum代的目标值均值
		Float[] aveOfObjVal1 = new Float[maxIterNum];
		Float[] aveOfObjVal2 = new Float[maxIterNum];
		Float[] aveOfObjVal3 = new Float[maxIterNum];
		
		//初始化,sumOfObjVal1[0]表示第1代的目标值1总和
		for(int i=0;i<maxIterNum;i++){
			sumOfObjVal1[i]=(float)0;
			sumOfObjVal2[i]=(float)0;
			sumOfObjVal3[i]=(float)0;
			aveOfObjVal1[i]=(float)0;
			aveOfObjVal2[i]=(float)0;
			aveOfObjVal3[i]=(float)0;
		}
		//对每i代的目标值进行求和	
		for(int j=0;j<runIDs.size();j++){
			String runID = runIDs.get(j);
			List<ChromOut> chromOuts = dbAccess.getBestChroms(runID);
			for(int i=0;i<maxIterNum;i++){
			sumOfObjVal1[i] += chromOuts.get(i).getObjVal1();
			sumOfObjVal2[i] += chromOuts.get(i).getObjVal2();
			sumOfObjVal3[i] += chromOuts.get(i).getObjVal3();
			}
			
		}
		//求第i代的最优目标值的均值	
		for(int i=0;i<maxIterNum;i++){
			aveOfObjVal1[i] = sumOfObjVal1[i]/runIDs.size();
			aveOfObjVal2[i] = sumOfObjVal2[i]/runIDs.size();
			aveOfObjVal3[i] = sumOfObjVal3[i]/runIDs.size();
			
		}
		/*
		 * 求解平均首达最优解代数
		 * eveFirstReachBestGenNum表示每一次运行哪一代最优的代数
		 * sumOfFirstReachBestGenNum 多次运行每一次运行最优代数的代数和
		 * eveFirstGenVal 用于求出哪一代最优的临时变量
		 */
		int eveFirstReachBestGenNum=1;
		int sumOfFirstReachBestGenNum = 0;
		float eveFirstGenVal = Float.MAX_VALUE;
		for(int i=0;i<runIDs.size();i++){
			String runID = runIDs.get(i);
			List<ChromOut> chromOuts = dbAccess.getBestChroms(runID);
			for(int j=0;j<maxIterNum;j++){
				if(chromOuts.get(j).getObjVal1()<eveFirstGenVal){
					eveFirstGenVal = chromOuts.get(j).getObjVal1();
					eveFirstReachBestGenNum=j+1;
				}
			}
			sumOfFirstReachBestGenNum+=eveFirstReachBestGenNum;
		}
		//aveFirstReachBestGen表示平均首达最优解代数
		double aveFirstReachBestGen = sumOfFirstReachBestGenNum*1.0/runIDs.size();
	
		/*
		 * 开始将数据装入单元格
		 */
		
		//总运行次数
		List<DataCell> row1 = new ArrayList<DataCell>();
			DataCell sumOfRun = new DataCell();
			sumOfRun.setName("总运行次数:"+runIDs.size());
			row1.add(sumOfRun);
			
		rlts.add(row1);
		//平均首达最优解代数
		List<DataCell> row2 = new ArrayList<DataCell>();
			DataCell aveGen = new DataCell();
			aveGen.setName("平均首达最优解代数:"+aveFirstReachBestGen);
			row2.add(aveGen);
			
		rlts.add(row2);
		
		for(int i=0;i<maxIterNum;i++){
			List<DataCell> row = new ArrayList<DataCell>();
			
				DataCell dataCell1 = new DataCell();
				dataCell1.setName("演化代数:"+(i+1));
				row.add(dataCell1);
				
				DataCell dataCell2 = new DataCell();
				dataCell2.setName("目标值1均值="+aveOfObjVal1[i]);
				row.add(dataCell2);
				
				DataCell dataCell3 = new DataCell();
				dataCell3.setName("目标值2均值="+aveOfObjVal2[i]);
				row.add(dataCell3);	
				
				DataCell dataCell4 = new DataCell();
				dataCell4.setName("目标值3均值="+aveOfObjVal3[i]);
				row.add(dataCell4);
			rlts.add(row);
		}
		return rlts;
	}
		
	/*
	 * 得到算法在一次运行过程中，每代种群中每个染色体的情况
	 */
	public List<List<DataCell>> getPopOut(String runID){	
		int popSize = gaPara.getPopuSize();
		List<List<ChromOut>>  multiChromOuts = dbAccess.getPopuOut(runID,popSize);		
		List<List<DataCell>> rlts = new ArrayList<List<DataCell>>();
	
		//按照excel格式将个体进行装配
		for (int i = 0; i < multiChromOuts.size(); i++) {
			
			// 输出Population1 Population1：的格式
			List<DataCell> rowPopu = new ArrayList<DataCell>();
			DataCell popuNameCell = new DataCell();
			popuNameCell.setName("Population" + (i+1));
			rowPopu.add(popuNameCell);
			DataCell popuCtxCell = new DataCell();
			popuCtxCell.setName("Population" + (i+1) + ":");
			rowPopu.add(popuCtxCell);
			rlts.add(rowPopu);

			// 输出bestChrom:1,3   {[1,2,3]:objVal1=456.0,objVal2=0.0;...}的格式
			List<DataCell> chromRow = new ArrayList<DataCell>();
			DataCell chromCell = new DataCell();
			DataCell objCell = new DataCell();
			String bestChrom = "bestChrom:";
			String objVal = "{";
			for (int j = 0; j < multiChromOuts.get(i).size(); j++) {			
				String codes  =  multiChromOuts.get(i).get(j).getCodes();
				float objVal1 =  multiChromOuts.get(i).get(j).getObjVal1();
				float objVal2 =  multiChromOuts.get(i).get(j).getObjVal2();
				float objVal3 =  multiChromOuts.get(i).get(j).getObjVal3();
				boolean isBest=  multiChromOuts.get(i).get(j).getBest();
				
				if (isBest) {// 判断是否是最优解
					bestChrom=bestChrom+j+",";
				} 
				
				objVal = objVal+ codes + ":" + "objVal1=" + objVal1 + ",objVal2=" + objVal2 + ",objVal3="
						+ objVal3 + ";"+ "\n";

				}
			bestChrom = bestChrom.substring(0,bestChrom.length()-1);
			objVal = objVal.substring(0,objVal.length()-2)+"}";
			chromCell.setName(bestChrom);
			objCell.setName(objVal);
			chromRow.add(chromCell);
			chromRow.add(objCell);
			rlts.add(chromRow);
			// 输出chrom0 [1,2,3]:objVal1=456.0,objVal2=0.0的格式
//			List<DataCell> chromRow =null;
//			for (int j = 0; j < popSize; j++) {			
//				String codes  =  multiChromOuts.get(i).get(j).getCodes();
//				float objVal1 =  multiChromOuts.get(i).get(j).getObjVal1();
//				float objVal2 =  multiChromOuts.get(i).get(j).getObjVal2();
//				float objVal3 =  multiChromOuts.get(i).get(j).getObjVal3();
//				boolean isBest=  multiChromOuts.get(i).get(j).getBest();
//		
//				chromRow = new ArrayList<DataCell>();
//				DataCell chromCell = new DataCell();
//				if (isBest) {// 判断是否是最优解
//					chromCell.setName("bestChrom" + j + "*");
//				} else {
//					chromCell.setName("chrom" + j);
//				}
//				chromRow.add(chromCell);
//	
//				DataCell objCell = new DataCell();
//				objCell.setName("[" + codes + "]:" + "objVal1=" + objVal1 + ",objVal2=" + objVal2+ ",objVal3=" + objVal3);
//				chromRow.add(objCell);
//				rlts.add(chromRow);
//				}
			}
			
		return rlts;
	}
	public void closeDBConn(){
		if(dbAccess!=null){
			dbAccess.closeDBCon();
		}
	}
}
